package com.cavedroid;

import android.opengl.GLSurfaceView;
import android.os.SystemClock;
import android.util.Log;

public class GameThread extends Thread {	
	
	public static final int OBSTACLE_FREQUENCY_CHANGE_INTERVAL = 750; 
	
	public static final int OBSTACLE_STOP_POINT = 2500;
	
	private static final float FORWARD_SPEED = 0.15f;
	
	private static final float UPWARD_ACCELERATION = 0.0108f; //0.03
	
	private static final float DOWNWARD_ACCELERATION = 0.0108f;
	
	private static final int SCORE_INCREASE = 2;
	
	private static final float RED_WARNING = 3.0f;
	
	private static final long TIME_UNIT = 30;
	
	private static final int VIBRATE_TIME = 80;
	
	protected int obstacleFrequency = 0;
	
	private int timerCount;
	
	
	public boolean showWarning;
	
	public int score = 0;
	
	public boolean touched = false;
	
	public float verticalVelocity = 0;
	
	public Cave cave;
	
	public CaveViewActivity parentActivity;
	
	public GLSurfaceView mGLSurfaceView;
	
	public GameThread(CaveViewActivity a) {
		super();
		parentActivity = a;
		cave = a.renderer.cave;
		mGLSurfaceView = parentActivity.mGLSurfaceView;
		showWarning = parentActivity.showWarning;
	}
	
	protected boolean notRunnable() {
		return gamePaused;
	}
	
	@Override
	public void run() {
		long thisTime;
		long workTime = 0;
		onResume();
		while(gameRunning) {
			try {
				sleep(Math.max(TIME_UNIT - workTime, 0));
				
				synchronized (this) {
					if (notRunnable()) {
						while (notRunnable())
							wait();
					}
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			thisTime = SystemClock.elapsedRealtime();
			updateState();
			workTime = SystemClock.elapsedRealtime() - thisTime;
		}
	}
	
	private boolean gameRunning = true;
	
	private boolean gamePaused = false;
	
	public void onEnd() {
		gameRunning = false;
	}
	
	public void onPause() {
		gamePaused = true;
	}
	
	public void onResume() {
		gamePaused = false;
		synchronized (this) {
			notify();
		}
	}
	
	public void updateState() {
		//Check for collisions
		float distance = cave.getCrashDistance();
		if (distance < 0) {
			//Vibrate on crash
			parentActivity.vibrator.vibrate(VIBRATE_TIME);
			parentActivity.uiHandler.post(parentActivity.endGame);
			onEnd();
			parentActivity.started = false;
			return;
		} else {
			if (showWarning) { 
				if (distance < RED_WARNING/2) {
					cave.tunnelColor[0] = 1;
					cave.tunnelColor[1] = distance/(RED_WARNING/2);
				} else if (distance < RED_WARNING) {
					cave.tunnelColor[0] = RED_WARNING/distance - 1;
					cave.tunnelColor[1] = 1;
				} else {
					cave.tunnelColor[0] = 0;
					cave.tunnelColor[1] = 1;
				}
			}
		}
		
		//Go forward
		cave.cameraZ -= FORWARD_SPEED;
		
		//Move vertically
		cave.cameraY += verticalVelocity;
		
		//Read input
		readInput();
		
		//Rotate cube
		if (cave.collectible.visible) {
			cave.collectible.rotation += 5;
		}
		
		//Increase obstacle frequency if necessary
		if (timerCount % OBSTACLE_FREQUENCY_CHANGE_INTERVAL == 0) {
			if (timerCount > OBSTACLE_STOP_POINT) {
				if (obstacleFrequency > 0) {
					obstacleFrequency--;
				}
			} else if (obstacleFrequency < Obstacles.MAX_NUMBER_OF_OBSTACLES - 1) {
				obstacleFrequency++;
			}
		}
		
		if (cave.collectibleCollision()) {
			score += 200;
			cave.collectible.visible = false;
			parentActivity.uiHandler.post(parentActivity.showPlus200);
			parentActivity.uiHandler.postDelayed(parentActivity.hidePlus200, 1000);
		}
		
		//Increase score
		score += SCORE_INCREASE;
		if (score % 20 == 0) {
			parentActivity.uiHandler.post(parentActivity.updateScoreDisplay);
		}
		
		while (cave.cameraZ - cave.currentLoopDepth < Cave.TOTAL_NUMBER_OF_RINGS*Cave.LOOP_DEPTH) {
			cave.genSpiralSegment();
			if (cave.spiralIterator == 0) {
				if (cave.spiralLoopCount % (Cave.TOTAL_NUMBER_OF_RINGS) == 0) {
					addCollectible();
				} else if (obstacleFrequency > 0 && cave.spiralLoopCount % (Cave.TOTAL_NUMBER_OF_RINGS/obstacleFrequency) == 0) {
					addObstacle();
				}
			}
		}
		
		mGLSurfaceView.requestRender();
		timerCount++;
	}
	
	//TODO: Kinda messy, fix up.
	protected void addObstacle() {
		cave.obstacles.newObstacle(cave.loopX, cave.loopY, cave.currentLoopDepth, cave.loopRadius);
	}
	
	//TODO: Kinda messy, fix up.
	protected void addCollectible() {
		cave.collectible.position(cave.loopX, cave.loopY + (cave.loopRadius-4*Collectible.SIZE)*((float)Math.random()*2-1), cave.currentLoopDepth);
	}
	
	protected void readInput() {
		if (touched) {
			verticalVelocity += UPWARD_ACCELERATION;
		} else {
			verticalVelocity -= DOWNWARD_ACCELERATION;
		}
	}
};
